package com.ruoyi.system.service.impl;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.AppActivityStatsTaskProgressVO;
import com.ruoyi.system.domain.dto.AppActivityTrendDTO;
import com.ruoyi.system.domain.dto.TaskProgressDTO;
import com.ruoyi.system.domain.vo.*;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.service.IAppActivityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class AppActivityServiceImpl implements IAppActivityService {

    @Resource
    private TbTaskDetailMapper tbTaskDetailMapper;

    @Resource
    private TbTaskTargetMapper taskTargetMapper;

    @Resource
    private TbTaskMapper tbTaskMapper;
    @Resource
    private TbTaskTargetMapper tbTaskTargetMapper;

    @Resource
    private TbDeviceMapper tbDeviceMapper;


    @Resource
    private TbAirplaneMapper airplaneMapper;


    @Resource
    private TbDeviceInfoMapper tbDeviceInfoMapper;

    @Override
    public List<AppActivityTrendVO> getActivityTrendData(LocalDate startDate, LocalDate endDate, String planeCode) {
        if (startDate == null || endDate == null || startDate.isAfter(endDate)) {
            return Collections.emptyList();
        }
        List<AppActivityTrendDTO> data = tbTaskDetailMapper.selectTaskDetailCountByTaskType(startDate, endDate, planeCode);
        // 转换为VO并填充可能缺失的日期
        return fillMissingDates(data, startDate, endDate);
    }

    @Override
    public List<AppActivityStatsTaskProgressVO> getActivityStatsProgress(LocalDate startDate, LocalDate endDate, String planeCode) {
        // 查询应用进度
        if (startDate == null || endDate == null || startDate.isAfter(endDate)) {
            return Collections.emptyList();
        }
        // 开始时间
        LocalDateTime startDateTime = startDate.atStartOfDay();
        // 结束时间
        LocalDateTime endDateTime = endDate.atTime(23, 59, 59);
        // 查询应用进度
        List<TaskProgressDTO> appProgress = tbTaskDetailMapper.selectAppProgress(startDateTime, endDateTime, planeCode);

        // 查询数据包进度
//        List<TaskProgressDTO> packageProgress = tbTaskDetailMapper.selectPackageProgress(
//                startDateTime,
//                endDateTime
//        );
        // 合并结果
        List<AppActivityStatsTaskProgressVO> result = new ArrayList<>();

        // 转换应用进度
        appProgress.forEach(dto -> result.add(new AppActivityStatsTaskProgressVO(1, dto.getName(), dto.getProgress())));

        // 转换数据包进度
//        packageProgress.forEach(dto -> result.add(new AppActivityStatsTaskProgressVO(2,
//                dto.getName(),
//                dto.getProgress()
//        )));

        return result;

    }

    @Override
    public List<AppActivityStatsTaskFailInfoVO> getAppActivityStatsFailDeviceList(LocalDate startDate, LocalDate endDate, String planeCode) {
        if (startDate == null || endDate == null || startDate.isAfter(endDate)) {
            return Collections.emptyList();
        }
        return tbTaskDetailMapper.getAppActivityStatsFailDeviceList(startDate, endDate, planeCode);
    }

    @Override
    public List<TbTaskProgressVO> getAppActivityTaskProgress(LocalDate startDate,
                                                             LocalDate endDate, String planeCode) {
        if (startDate == null || endDate == null || startDate.isAfter(endDate)) {
            return Collections.emptyList();
        }

        // 1. 查询符合条件的任务
        List<TbTask> tasks = tbTaskMapper.selectTasksByDateRange(
                startDate.atStartOfDay(),
                endDate.plusDays(1).atStartOfDay(),
                planeCode
        );

        // 2. 计算每个任务的进度
        return tasks.stream()
                .map(task -> calculateTaskProgress(task, planeCode))
                .collect(Collectors.toList());
    }

    private TbTaskProgressVO calculateTaskProgress(TbTask task, String planeCode) {
        TbTaskProgressVO vo = new TbTaskProgressVO();
        vo.setTaskId(task.getId());
        vo.setTaskName(task.getTaskName());
        vo.setTaskStatus(task.getTaskStatus());
        vo.setCreateTime(task.getCreateTime());
        // 获取任务的所有明细
        List<TbTaskDetail> taskDetails = tbTaskDetailMapper.selectByTaskId(task.getId());

        if (taskDetails.isEmpty()) {
            vo.setProgress(0.0);
            return vo;
        }

        // 计算总体进度（按明细加权平均）
        double totalProgress = 0.0;
        int detailCount = taskDetails.size();

        for (TbTaskDetail detail : taskDetails) {
            double detailProgress = calculateDetailProgress(detail, planeCode);
            totalProgress += detailProgress;
        }

        vo.setProgress(totalProgress / detailCount);
        return vo;
    }

    private double calculateDetailProgress(TbTaskDetail detail, String planeCode) {
        // 获取明细的所有目标设备
        List<TbTaskTarget> targets = tbTaskTargetMapper.selectByDetailId(detail.getId());

        if (targets.isEmpty()) {
            return 0.0;
        }

        // 如果指定了飞机号，过滤设备
        if (StringUtils.isNotBlank(planeCode)) {
            targets = targets.stream()
                    .filter(target -> {
                        TbDevice device = tbDeviceMapper.selectTbDeviceById(target.getDeviceId());
                        return device != null && planeCode.equals(device.getAirplaneCode());
                    })
                    .collect(Collectors.toList());

            if (targets.isEmpty()) {
                return 0.0;
            }
        }

        // 计算该明细的平均进度
        double totalTargetProgress = 0.0;
        for (TbTaskTarget target : targets) {
            totalTargetProgress += target.getProgress() != null ? target.getProgress() : 0.0;
        }
        return totalTargetProgress / targets.size();
    }


    @Override
    public List<TbAirplaneMapVO> getAirPlaneMap(String planeCode, LocalDate startDate, LocalDate endDate) {
        if (startDate == null || endDate == null || startDate.isAfter(endDate)) {
            log.warn("日期参数无效: startDate={}, endDate={}", startDate, endDate);
            return Collections.emptyList();
        }

        LocalDateTime startDateTime = startDate.atStartOfDay();
        LocalDateTime endDateTime = endDate.atTime(23, 59, 59);
        log.info("查询地图概览: planeCode={}, 时间段={} 至 {}", planeCode, startDateTime, endDateTime);
        // 1. 查询在指定时间段内有位置信息的飞机
        List<TbAirplane> airplanes;
        if (StringUtils.isNotBlank(planeCode)) {
            // 如果指定了飞机号，查询该飞机且在时间段内有位置信息
            airplanes = airplaneMapper.selectByPlaneCodeWithLocation(planeCode);
        } else {
            // 查询所有在时间段内有位置信息的飞机
            airplanes = airplaneMapper.selectAllWithLocationInPeriod();
        }

        if (airplanes.isEmpty()) {
            log.info("未找到在时间段 {} 至 {} 内有位置信息的飞机", startDateTime, endDateTime);
            return Collections.emptyList();
        }
        // 2. 获取飞机编码列表
        List<String> planeCodes = airplanes.stream()
                .map(TbAirplane::getPlaneCode)
                .distinct()
                .collect(Collectors.toList());

        // 3. 查询这些飞机关联的设备
        List<TbDevice> devices = tbDeviceMapper.selectByAirplaneCodes(planeCodes);
        if (devices.isEmpty()) {
            log.info("飞机 {} 未找到关联的设备", planeCodes);
            return convertToEmptyResult(airplanes);
        }

        // 4. 获取所有设备SN
        List<String> deviceSns = devices.stream()
                .map(TbDevice::getDevSn)
                .distinct()
                .collect(Collectors.toList());
        // 5. 查询设备在时间段内的位置信息（每个设备的最新位置）
        List<TbDeviceInfo> deviceInfos = tbDeviceInfoMapper.selectLatestLocationByDeviceSns(
                deviceSns, startDateTime, endDateTime);
        if (deviceInfos.isEmpty()) {
            log.info("设备 {} 在时间段 {} 至 {} 内没有位置信息", deviceSns, startDateTime, endDateTime);
            return convertToEmptyResult(airplanes);
        }

        // 6. 按位置分组设备信息
        Map<String, List<TbDeviceInfo>> locationGroups = deviceInfos.stream()
                .filter(deviceInfo -> deviceInfo.getLongitude() != null &&
                        deviceInfo.getLatitude() != null &&
                        deviceInfo.getAltitude() != null)
                .collect(Collectors.groupingBy(
                        deviceInfo -> String.format("%.6f,%.6f,%.1f",
                                deviceInfo.getLongitude(),
                                deviceInfo.getLatitude(),
                                deviceInfo.getAltitude())
                ));

        // 7. 构建返回结果 - 按位置分组，每个位置也可能包含多个飞机
        List<TbAirplaneMapVO> result = new ArrayList<>();

        for (Map.Entry<String, List<TbDeviceInfo>> entry : locationGroups.entrySet()) {
            List<TbDeviceInfo> locationDevices = entry.getValue();

            // 获取该位置的所有设备对应的飞机
            Map<String, List<DeviceInfoVO>> planeDevicesMap = new HashMap<>();

            for (TbDeviceInfo deviceInfo : locationDevices) {
                // 找到该设备对应的飞机
                String deviceSn = deviceInfo.getDevSn();
                TbDevice device = devices.stream()
                        .filter(d -> d.getDevSn().equals(deviceSn))
                        .findFirst()
                        .orElse(null);

                if (device != null && device.getAirplaneCode() != null) {
                    String airplaneCode = device.getAirplaneCode();

                    // 转换设备信息为VO
                    DeviceInfoVO deviceInfoVO = convertToDeviceInfoVO(deviceInfo);

                    // 按飞机号分组设备
                    planeDevicesMap.computeIfAbsent(airplaneCode, k -> new ArrayList<>())
                            .add(deviceInfoVO);
                }
            }

            // 为每个位置的每个飞机构建VO对象
            for (Map.Entry<String, List<DeviceInfoVO>> planeEntry : planeDevicesMap.entrySet()) {
                String airplaneCode = planeEntry.getKey();
                List<DeviceInfoVO> planeDevices = planeEntry.getValue();
                //获取到设备sn列表
                List<String> planeDeviceSns = planeDevices.stream().collect(Collectors.mapping(DeviceInfoVO::getDevSn, Collectors.toList()));
                //获取设备详情
                List<TbDevice> planeDeviceDetails = tbDeviceMapper.selectByDeviceSnsList(planeDeviceSns);
                TbAirplaneMapVO vo = new TbAirplaneMapVO();
                vo.setPlaneCode(airplaneCode);

                // 设置飞机状态
                airplanes.stream()
                        .filter(airplane -> airplane.getPlaneCode().equals(airplaneCode))
                        .findFirst()
                        .ifPresent(airplane -> vo.setStatus(airplane.getStatus()));

                // 设置设备列表
                vo.setDevices(planeDeviceDetails);

                // 设置位置信息（从第一个设备获取）
                if (!locationDevices.isEmpty()) {
                    TbDeviceInfo firstDevice = locationDevices.get(0);
                    vo.setLongitude(firstDevice.getLongitude());
                    vo.setLatitude(firstDevice.getLatitude());
                    vo.setAltitude(firstDevice.getAltitude());
                }

                result.add(vo);
            }
        }
        return result;
    }

    // 转换方法：TbDeviceInfo -> DeviceInfoVO
    private DeviceInfoVO convertToDeviceInfoVO(TbDeviceInfo deviceInfo) {
        DeviceInfoVO vo = new DeviceInfoVO();
        vo.setId(deviceInfo.getId());
        vo.setDevSn(deviceInfo.getDevSn());
        vo.setOsVer(deviceInfo.getOsVer());
        vo.setRomTotal(deviceInfo.getRomTotal());
        vo.setDevModel(deviceInfo.getDevModel());
        vo.setCpuInfo(deviceInfo.getCpuInfo());
        vo.setMemoryTotal(deviceInfo.getMemoryTotal());
        vo.setBatteryHealth(deviceInfo.getBatteryHealth());
        vo.setCreateBy(deviceInfo.getCreateBy());
        vo.setCreateTime(deviceInfo.getCreateTime());
        vo.setUpdateBy(deviceInfo.getUpdateBy());
        vo.setUpdateTime(deviceInfo.getUpdateTime());
        vo.setHardwareVersion(deviceInfo.getHardwareVersion());
        vo.setPowerOnTime(deviceInfo.getPowerOnTime());
        vo.setPowerOnHours(deviceInfo.getPowerOnHours());
        vo.setPowerOnCount(deviceInfo.getPowerOnCount());
        vo.setUsbState(deviceInfo.getUsbState());
        vo.setLcmTemperature(deviceInfo.getLcmTemperature());
        vo.setPcbTemperature(deviceInfo.getPcbTemperature());
        vo.setCpuTemperature(deviceInfo.getCpuTemperature());
        vo.setMemUsage(deviceInfo.getMemUsage());
        vo.setStorageUsage(deviceInfo.getStorageUsage());
        vo.setCpuUsage(deviceInfo.getCpuUsage());
        vo.setMemoryFree(deviceInfo.getMemoryFree());
        vo.setScreenTemp(deviceInfo.getScreenTemp());
        vo.setFanSpeed(deviceInfo.getFanSpeed());
        vo.setMotherboardTemp(deviceInfo.getMotherboardTemp());
        vo.setConnectionStatus(deviceInfo.getConnectionStatus());
        vo.setCurrentTask(deviceInfo.getCurrentTask());
        vo.setLastUpgradeStatus(deviceInfo.getLastUpgradeStatus());
        vo.setVersionIdInfo(deviceInfo.getVersionIdInfo());
        vo.setLongitude(deviceInfo.getLongitude());  // 重要：经度
        vo.setLatitude(deviceInfo.getLatitude());    // 重要：纬度
        vo.setAltitude(deviceInfo.getAltitude());    // 重要：高度
        vo.setPwrOnMinReal(deviceInfo.getPwrOnMinReal());
        vo.setPwrOnMinTemp(deviceInfo.getPwrOnMinTemp());

        return vo;
    }

    /**
     * 构建空结果
     */
    private List<TbAirplaneMapVO> convertToEmptyResult(List<TbAirplane> airplanes) {
        return airplanes.stream()
                .map(airplane -> {
                    TbAirplaneMapVO vo = new TbAirplaneMapVO();
                    vo.setPlaneCode(airplane.getPlaneCode());
                    vo.setStatus(airplane.getStatus());
                    vo.setDevices(Collections.emptyList());
                    return vo;
                })
                .collect(Collectors.toList());
    }






    private List<AppActivityTrendVO> fillMissingDates(List<AppActivityTrendDTO> dbData, LocalDate startDate, LocalDate endDate) {
        // 创建日期范围到VO对象的映射
        Map<LocalDate, AppActivityTrendVO> resultMap = new LinkedHashMap<>();

        // 初始化所有日期
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            AppActivityTrendVO vo = new AppActivityTrendVO();
            vo.setDate(date);
            vo.setInstallCount(0);
            vo.setContentUpdateCount(0);
            vo.setAppUpdateCount(0);
            vo.setUninstallCount(0);
            resultMap.put(date, vo);
        }

        // 填充有数据的日期
        dbData.forEach(dto -> {
            AppActivityTrendVO vo = resultMap.get(dto.getDate());
            if (vo != null) {
                vo.setInstallCount(dto.getInstallCount());
                vo.setContentUpdateCount(dto.getContentUpdateCount());
                vo.setAppUpdateCount(dto.getAppUpdateCount());
                vo.setUninstallCount(dto.getUninstallCount());
            }
        });

        return new ArrayList<>(resultMap.values());
    }
}
